// 简单版
Page({
  data: {
    // 前端输入内容
    content: '',
    // 后端反馈数据
    feedbackContent: '',
    // 当前登录者信息
    login: {
      nickName: '',
      avatar: ''
    },
    // 聊天信息
    chatList: [],
    // websocket相关属性数据
    socketStatus: null, //记录websocket连接状态
    SocketTask: null, //socket链接后的对象，可以进行关闭发消息收消息等
    lockReconnect: false, //重连锁，防止重复连接
    wsCreateHandler: null, //重连时间句柄
    timeoutObj: null, //心跳检测时间句柄
    serverTimeoutObj: null, //心跳检测服务器响应时间句柄
  },
  onLoad() {
    // 检测该用户的jwt是否已经失效
    wx.request({
      url: getApp().globalData.commonIP + '/wxuser/monitorJWT',
      method: 'GET',
      header: {
        'content-type': 'application/json',
        'token': wx.getStorageSync('token')
      },
      success: res => {
        if (res.data.msg == "token过期，请重新登录" || res.data.msg == "token失效，请重新登录" || res.data.msg == "无效签名，请重新登录" || res.data.msg == "token算法不一致，请重新登录") {
          wx.showModal({
            title: '提示',
            content: res.data.msg,
            showCancel: false,
            complete: (res) => {
              if (res.cancel) {

              }

              if (res.confirm) {
                // 重置全局变量和去除缓存
                getApp().globalData.wxusername = ''
                getApp().globalData.wxuseravatar = ''
                wx.removeStorageSync('nickName')
                wx.removeStorageSync('avatarUrl')
                wx.removeStorageSync('token')

                wx.switchTab({
                  url: '/pages/index/index'
                })
              }
            }
          })
          return
        }
      }
    })
    // 加载已有聊天记录
    this.setData({
      socketStatus: getApp().globalData.socketStatus,
      chatList: getApp().globalData.chatList,
      login: {
        nickName: getApp().globalData.wxusername,
        avatar: getApp().globalData.wxuseravatar
      }
    })
    // 弹出页面提示
    this.scrollToBottom()
    // 建立ws连接
    let that = this
    if (that.data.socketStatus === 'closed') {
      that.openSocket();
    }
  },

  onUnload() {
    // 保存聊天记录
    getApp().globalData.chatList = this.data.chatList
    // 关闭ws链接
    this.closeSocket()
  },

  onHide() {
    // 保存聊天记录
    getApp().globalData.chatList = this.data.chatList
    // 关闭ws链接
    this.closeSocket()
  },


  // 输入监听
  inputClick(e) {
    this.setData({
      content: e.detail.value
    })
  },

  // 发送监听
  sendClick() {
    var that = this;
    var list = this.data.chatList;
    // 获取当前时间
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var hour = date.getHours();
    var minu = date.getMinutes();
    var now1 = month < 10 ? '0' + month : month;
    var now2 = day < 10 ? '0' + day : day;
    // 组装发送端数据
    var msg = {
      nickName: this.data.login.nickName,
      avatar: this.data.login.avatar,
      message: this.data.content,
      date: year + '-' + now1 + '-' + now2 + ' ' + hour + ':' + minu
    }
    // 及时更新此消息
    that.setData({
      chatList: list.concat(msg)
    }, () => {
      that.scrollToBottom();
      that.setData({
        content: ''
      })
    })
    // 向服务端发送消息
    this.sendMessage(msg)
  },

  // 滑动到最底部
  scrollToBottom() {
    setTimeout(() => {
      wx.pageScrollTo({
        scrollTop: 200000,
        duration: 3
      });
    }, 600)
  },

  // 建立ws链接
  openSocket() {
    try {
      // 连接后台服务器
      this.SocketTask = wx.connectSocket({
        url: getApp().globalData.wsIP + '/' + getApp().globalData.wxusername
      })
    } catch (e) {
      // console.log(e)
      // 服务器重连
      this.ReConnect()
    }
    //连接成功后的操作
    //可以处理一些在线和非在线的情况，比如已经连接可以设置该用户头像高亮显示等等
    this.SocketTask.onOpen(() => {
      console.log('WebSocket 已连接')
      this.startHeartCheck()
      this.socketStatus = 'connected';
      getApp().globalData.socketStatus = 'connected';
    })
    //断开后台服务器的操作
    this.SocketTask.onClose(() => {
      console.log('WebSocket 已断开')
      this.socketStatus = 'closed'
      getApp().globalData.socketStatus = 'closed';
      // this.ReConnect()
    })
    //报错时执行
    this.SocketTask.onError(error => {
      this.socketStatus = 'closed'
      getApp().globalData.socketStatus = 'closed';
      this.ReConnect()
    })
    // 监听服务器推送的消息
    this.SocketTask.onMessage(message => {
      console.log('收到回复：', message)
      // 排除心跳回复
      if ("I am alive..." === message.data) {
        return
      }
      this.startHeartCheck()
      let responseMsg = JSON.parse(message.data)
      console.log(responseMsg)
      // 及时更新回复状态
      this.setData({
        chatList: this.data.chatList.concat(responseMsg)
      }, () => {
        this.scrollToBottom();
      })
    })
  },

  // 关闭websocket服务
  closeSocket() {
    if (this.socketStatus === 'connected') {
      this.SocketTask.close({
        success: () => {
          this.socketStatus = 'closed'
          getApp().globalData.socketStatus = 'closed'
        }
      })
    }
  },

  //发送消息函数
  sendMessage(msg) {
    if (this.socketStatus === 'connected') {
      //群发，没有指定发送对象
      /*
      this.SocketTask.send({
        data: this.data.inputStr  
      })
      */
      // 点对点发送：一般会给后端传送json数据
      let jsonStr = JSON.stringify(msg)
      this.SocketTask.send({
        data: jsonStr,
      })
    }
  },

  //重连方法
  ReConnect() {
    //如果锁被锁住就直接返回
    if (this.lockReconnect)
      return
    console.log("重新连接...")
    this.lockReconnect = true
    //没有连接上会一直重连，为了防止请求次数过多一般设置等待时间
    this.wsCreateHandler && clearTimeout(this.wsCreateHandler)
    this.wsCreateHandler = setTimeout(() => {
      this.openSocket()
      this.lockReconnect = false
    }, 2000)
  },

  // 心跳检测部分:网络中断等问题系统无法捕获，需要用心跳检测实现重连
  // 重启心跳检测
  resetHeartCheck() {
    clearTimeout(this.timeoutObj)
    clearTimeout(this.serverTimeoutObj)
    this.startHeartCheck()
  },

  //开启心跳检测定时器
  startHeartCheck() {
    this.timeoutObj && clearTimeout(this.timeoutObj)
    this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
    this.timeoutObj = setTimeout(() => {
      console.log("发送ping到服务器")
      try {
        this.SocketTask.send({
          data: "ping"
        })
      } catch (e) {
        console.log("发送ping失败")
      }
      //内嵌计时器，防止刚连上后立刻重连
      this.serverTimeoutObj = setTimeout(() => {
        //没有收到后台的数据关闭连接后重连
        // this.closeSocket()
        this.ReConnect()
      }, 150000)
    }, 150000)
  }

})